#ifndef HGL_STR_TEMPLATE_INCLUDE
#define HGL_STR_TEMPLATE_INCLUDE

#include<string.h>
namespace hgl
{
	/**
	 * 测试当前字符是否为小写字母
	 */
	template<typename T>
	bool islower(const T ch)
	{
		return(ch>='a'&&ch<='z');
	}

	/**
	 * 测试当前字符是否为大写字母
	 */
	template<typename T>
	bool isupper(const T ch)
	{
		return(ch>='A'&&ch<='Z');
	}

	/**
	 * 测试当前字符是否为字母
	 */
	template<typename T>
	bool isalpha(const T ch)
	{
		return(islower(ch)||isupper(ch));
	}

	/**
	 * 测试当前字符是否为10进制数字
	 */
	template<typename T>
	bool isdigit(const T ch)
	{
		return(ch>='0'&&ch<='9');
	}

	/**
	 * 测试当前字符是否为16进制数用字符(0-9,A-F)
	 */
	template<typename T>
	bool isxdigit(const T ch)
	{
		return((ch>='0'&&ch<='9')
			 ||(ch>='a'&&ch<='f')
			 ||(ch>='A'&&ch<='F'));
	}

	/**
	 * 是否为不显示可打印字符(' ','\t','\r','\f','\v','\n')
	 */
	template<typename T>
	bool isspace(const T ch)
	{
		return(ch==' '||ch=='\t'||ch=='\r'||ch=='\f'||ch=='\v'||ch=='\n');
	}

	/**
	 * 测试当前字符是否为字母或数字
	 */
	template<typename T>
	bool isalnum(const T ch)
	{
		return(isalpha(ch)&&isdigit(ch));
	}

	/**
	 * 如果当前字符为大写英文字符，则转换为小写
	 */
	template<typename T>
	T tolower(const T ch)
	{
		if(ch>='A'&&ch<='Z')
			return ch+('a'-'A');
		else
			return ch;
	}

	/**
	 * 如果当前字符为小写英文字符，则转换为大写
	 */
	template<typename T>
	T toupper(const T ch)
	{
		if(ch>='a'&&ch<='z')
			return ch+('A'-'a');
		else
			return ch;
	}

	/**
	 * 比较两个字符的大小(英文不区分大小写)
	 */
	template<typename T>
	int chricmp(T src,T dst)
	{
		return tolower(src)-tolower(dst);
	}

	/**
	* 对宽字符串计算字串长度
	* @param str 要计算长度的字符串指针
	* @return 字符串长度
	*/
	template<typename T>
	int strlen(const T *str)
	{
		if(str&&*str)
		{
			const T *start=str;

			while(*str++);

			return int(str-start-1);
		}

		return(0);
	}

	/**
	* 复制字符串
	* @param dst 目标字符串
	* @param src 源字符串
	*/
	template<typename T>
	void strcpy(T *dst,const T *src)
	{
		if(!dst)return;

		if(!src||!(*src))
			*dst=0;
		else
			while(((*dst++)=(*src++)));
	}

	/**
	* 复制字符串，并指定最大长度
	* @param dst 目标字符串
	* @param src 源字符串
	* @param count 最多复制多少个字符
	*/
	template<typename T>
	void strcpy(T *dst,int count,const T *src)
	{
		if(!dst)return;

		if(!src||!(*src)||count<=0)
		{
			//没什么好复制的
			*dst=0;
			return;
		}

		if(!src||!(*src))
			*dst=0;
		else
			while(((*dst++)=(*src++))&&count--);
	}

	/**
	* 复制字符串，并指定最大长度
	* @param dst 目标字符串
	* @param src 源字符串
	* @param count 最多复制多少个字符
	*/
	template<typename T>
	void strcpy(T *dst,const T *src,int count)
	{
		if(!dst)return;

		if(!src||!(*src)||count<=0)
		{
			//没什么好复制的
			*dst=0;
			return;
		}

		while(count&&(*dst++=*src++))
			count--;

		if(!count)		//如果是因为count到头了
			*dst=0;
	}

	/**
	* 在字符串str1内查找另一个字符串str2
	* @param str1 完整的字符串
	* @param str2 要查找的字符串
	* @return str2在str1中所在位置的指针
	*/
	template<typename T>
	T *strstr(T *str1,const T *str2)
	{
		T *cp = (T *) str1;
		T *s1, *s2;

		if ( !*str2)
			return (T *)str1;

		while (*cp)
		{
			s1 = cp;
			s2 = (T *) str2;

			while ( *s1 && *s2 && !(*s1-*s2) )
				s1++, s2++;

			if (!*s2)
				return(cp);

			cp++;
		}

		return(0);
	}

	/**
	* 复制一个字符到当前字符串后面
	* @param dst 目标字符串
	* @param src 源字符
	*/
	template<typename T>
	void strcat(T *dst,const T src)
	{
		if(!dst||!src)return;

		while(*dst++);			//找到结束
		dst--;

        *dst++=src;
        *dst=0;
	}

	/**
	* 复制一个字符串到当前字符串后面
	* @param dst 目标字符串
	* @param src 源字符串
	*/
	template<typename T>
	void strcat(T *dst,const T *src)
	{
		if(!dst||!src||!(*src))return;

		while(*dst++);			//找到结束
		dst--;

		while(((*dst++)=(*src++)));	//复制
	}

	/**
	* 复制一个字符串到当前字符串后面，并指定最大长度
	*/
	template<typename T>
	void strcat(T *dst,const T *src,int count)
	{
		if(!dst||!src||!(*src)||count<=0)return;

		while(*dst++);			//找到结束
			dst--;

		while(count&&(*dst++=*src++))
			count--;

		if(!count)
			*dst=0;
	}

	/**
	* 在字符串中查找某个字符
	* @param str 字符串
	* @param ch 字符
	* @return 查找到的位置指针
	*/
	template<typename T>
	T *strchr(const T *str,const T ch)
	{
		if(!str||!(*str))return(0);

		while(*str)
		{
			if(*str==ch)
				return((T *)str);
			else
				str++;
		}

		return(0);
	}

	/**
	* 在字符串中查找某个字符,指定字符串最大长度
	* @param str 字符串
	* @param ch 字符
	* @param n 字符串长度
	* @return 查找到的位置指针
	*/
	template<typename T>
	T *strchr(const T *str,const T ch,int n)
	{
		if(!str||!(*str))return(0);

		while(*str&&n--)
		{
			if(*str==ch)
				return((T *)str);
			else
				str++;
		}

		return(0);
	}

	/**
	* 在字符串中从结尾处开始查找某个字符
	* @param str 字符串
	* @param ch 字符
	* @return 查找到的位置指针
	*/
	template<typename T>
	T *strrchr(const T *str,const T ch)
	{
		if(!str||!(*str))return(0);

		T *result=0;

		while(*str)
		{
			if(*str==ch)result=(T *)str;

			str++;
		}

		return(result);
	}

	/**
	* 比较两个字符串的大小
	* @param src,dst 要比较的字符串
	* @return -1 src <  dst
	* @return  0 src == dst
	* @return +1 src >  dst
	*/
	template<typename T>
	int strcmp(const T *src,const T *dst)
	{
		if(!src)
		{
			if(!dst)return(0);
				else return(-1);
		}

		if(!dst)return(1);

		while((*src==*dst)&&(*src))
		{
			src++;
			dst++;
		}

		return(*src-*dst);
	}

	/**
	* 比较两个字符串的大小,并指定最大比较长度
	* @param src,dst 要比较的字符串
	* @param count 比较的最大长度
	* @return -1 src <  dst
	* @return  0 src == dst
	* @return +1 src >  dst
	*/
	template<typename T>
	int strcmp(const T *src,const T *dst,int count)
	{
		if(count<=0)return(0);

		if(!src)
		{
			if(!dst)return(0);
				else return(-1);
		}

		if(!dst)return(1);

		while((--count)&&(*src==*dst))
		{
			src++;
			dst++;
		}

		return(*src-*dst);
	}

	/**
	* 比较两个字符串的大小(英文不区大小写)
	* @param src,dst 要比较的字符串
	* @return -1 src <  dst
	* @return  0 src == dst
	* @return +1 src >  dst
	*/
	template<typename T>
	int stricmp(const T *src,const T *dst)
	{
		if(!src)
		{
			if(!dst)return(0);
				else return(-1);
		}

		if(!dst)return(1);

		int gap;

		while(*src&&*dst)
		{
			gap=chricmp(*src,*dst);

			if(gap)
				return gap;

   			src++;
   			dst++;
		}

		return(*src-*dst);
	}

	/**
	* 比较两个字符串的大小(英文不区大小写)
	* @param src,dst 要比较的字符串
	* @param count 比较的最大长度
	* @return -1 src <  dst
	* @return  0 src == dst
	* @return +1 src >  dst
	*/
	template<typename T>
	int stricmp(const T *src,const T *dst,int count)
	{
		if(!src)
		{
			if(!dst)return(0);
				else return(-1);
		}

		if(!dst)return(1);

		int gap;

		while((--count)&&(*src)&&(*dst))
		{
			gap=chricmp(*src,*dst);

			if(gap)
				return gap;

   			src++;
   			dst++;
		}

		return(*src-*dst);
	}

	/**
	 * 字符集字串比较<br>
	 * 不区字区大小写，不计算符号。如gb2312和gb-2312、gb_2312比较结果均为相同
	 */
	template<typename T>
	int charsetcmp(const T *src,const T *dst)
	{
		if(!src)
		{
			if(!dst)return(0);
				else return(-1);
		}

		if(!dst)return(1);

		int gap;

		while(true)
		{
			while(*src&&!isalnum(*src))src++;
			while(*dst&&!isalnum(*dst))dst++;

			gap=chricmp(*src,*dst);

			if(gap)
				return gap;

			src++;
			dst++;
		}

		return(*src-*dst);
	}

	/**
	 * 截去字符串前端所有的空格、换行等符号字符
	 * @param src 源字符串指针
	 * @param len 源字符串长度
	 * @return 新的字符串，需自行delete[]
	 */
	template<typename T>
	T *trimleft(const T *src,int &len)
	{
		const T *p=src;

		while(*p&&isspace(*p)&&len)
		{
			p++;
			len--;
		}

		if(len<=0)
			return(0);

		T *new_str=new T[len+1];

		memcpy(new_str,p,len*sizeof(T));
		new_str[len]=0;
		return new_str;
	}

	/**
	 * 截去字符串尾端所有的空格、换行等符号字符
	 */
	template<typename T>
	T *trimright(const T *src,int &len)
	{
		const T *p=src+len-1;

		while(isspace(*p)&&len)
		{
			p--;
			len--;
		}

		if(len<=0)
			return(0);

		T *new_str=new T[len+1];

		memcpy(new_str,src,len*sizeof(T));
		new_str[len]=0;
		return new_str;
	}

	/**
	 * 截去字符串前端和尾端的所有空格、换行符等符号
	 */
	template<typename T>
	T *trim(const T *src,int &len)
	{
		const T *sp=src;
		const T *ep=src+len-1;

		while(*sp&&isspace(*sp)&&len)
		{
			sp++;
			len--;
		}

		while(isspace(*ep)&&len)
		{
			ep--;
			len--;
		}

		if(len<=0)
			return(0);

		T *new_str=new T[len+1];

		memcpy(new_str,sp,len*sizeof(T));
		new_str[len]=0;
		return new_str;
	}

	/**
	* 给一个文件名更改扩展名
	* @param old_filename 原始文件名称
	* @param new_filename 新文件名称
	* @param new_extname 新扩展名(不带.)
	*/
	template<typename T>
	void ReplaceExtName(const T *old_filename,T *new_filename,const T *new_extname)
	{
		T *p=strrchr(old_filename,L'.');

		if(p)
		{
			strcpy(new_filename,old_filename,p-old_filename+1);
			strcpy(new_filename+(p-old_filename+1),new_extname);
		}
		else
		{
			const int l=strlen(old_filename);

			strcpy(new_filename,old_filename,l);
			new_filename[l]=L'.';
			strcpy(new_filename+l+1,new_extname);
		}
	}

	/**
	* 给一个文件名更改扩展名
	* @param filename 文件名称
	* @param new_extname 新扩展名(不带.)
	*/
	template<typename T>
	void ReplaceExtName(T *filename,const T *new_extname)
	{
		T *p=strrchr(filename,L'.');

		if(p)
		{
			strcpy(p+1,new_extname);
		}
		else
		{
			strcat(filename,L'.');
			strcat(filename,new_extname);
		}
	}

	/**
	* 创建一个复制
	* @param str 要复制的字符串
	* @param size 字符串长度,-1表示自动测试
	* @return 复制出来的字符串
	*/
	template<typename T>
	T *CreateCopy(const T *str,int size=-1)
	{
		if(!str)return(0);

		T *copy;

		if(size==-1)size=strlen(str);

		if(size==0)return(0);

		size++;

		copy=new T[size];
		strcpy(copy,str,size);

		return(copy);
	}

	/**
	* 将一个字符串中的某个字符全部替换为另一个字符
	* @param string 要处理的字符串
	* @param sch 要被替换掉的字符
	* @param tch 替换后的字符
	* @return 替换的次数
	*/
	template<typename T>
	int replace(T *str,const T tch,const T sch)
	{
		if(!str)
			return(0);

		int count=0;

		while(*str)
		{
			if(*str==sch)
			{
				*str=tch;
				count++;
			}

			str++;
		}

		return(count);
	}

	/**
	* 将一个字符串中的字母全部改为大写
	* @param SourceString 要处理的字符串
	*/
	template<typename T>
	void UpperString(T *SourceString)
	{
		if(!SourceString)return;

		while(*SourceString)
		{
			if(*SourceString>='a'&&*SourceString<='z')
				*SourceString-=32;

			SourceString++;
		}
	}


	/**
	* 将一个字符串中的字母全部改为小写
	* @param SourceString 要处理的字符串
	*/
	template<typename T>
	void LowerString(T *SourceString)
	{
		if(!SourceString)return;

		while(*SourceString)
		{
			if(*SourceString>='A'&&*SourceString<='Z')
				*SourceString+=32;

			SourceString++;
		}
	}

	/**
	* 将一个字符串中的字母全部改为大写
	* @param SourceString 要处理的字符串
	*/
	template<typename T>
	void UpperString(const T *SourceString,T *TargetString)
	{
		if(!TargetString)return;

		if(!SourceString)
		{
			*TargetString=0;
			return;
		}

		do
		{
			if(*SourceString>='A'&&*SourceString<='Z')
				*TargetString++=*SourceString-32;
			else
				*TargetString++=*SourceString;

			SourceString++;
		}while(*SourceString);

		*TargetString=0;
	}

	/**
	* 将一个字符串中的字母全部改为小写
	* @param SourceString 要处理的字符串
	*/
	template<typename T>
	void LowerString(const T *SourceString,T *TargetString)
	{
		if(!TargetString)return;

		if(!SourceString)
		{
			*TargetString=0;
			return;
		}

		do
		{
			if(*SourceString>='A'&&*SourceString<='Z')
				*TargetString++=*SourceString+32;
			else
				*TargetString++=*SourceString;

			SourceString++;
		}while(*SourceString);

		*TargetString=0;
	}

	/**
	* 统计在字符串中某个字符的出现次数
	* @param str 字符串
	* @param ch
	* @return 出现次数
	*/
	template<typename T>
	int StatChar(const T *str,const T ch)
	{
		if(!str)return(0);

		int count=0;

		while(*str)
		{
			if(*str++==ch)
				count++;
		}

		return(count);
	}

	/**
	* 统计一个字符串的行数
	*/
	template<typename T>
	int StatLine(const T *str)
	{
		if(!str)return(0);

		const T *p=str+strlen(str)-1;

		if(*p=='\n')return(StatChar(str,'\n'));
			else return(StatChar(str,'\n')+1);
	}

	template<typename R,typename S>
	bool stoi(const S *str,R &result)
	{
		if(!str)
			return(false);

		result=0;
		bool zf=true;

		if(*str=='-')
		{
			zf=false;
			str++;
		}

		while(*str&&*str>='0'&&*str<='9')
		{
			result*=10;
			result+=(*str-'0');

			str++;
		}

		if(!zf)
			result=-result;

		return(true);
	}

	template<typename R,typename S>
	bool stou(const S *str,R &result)
	{
		if(!str)
			return(false);

		result=0;

		while(*str)
		{
			if(*str>='0'&&*str<='9')
			{
				result*=10;
				result+=(*str-'0');

				str++;
			}
			else
				return(true);
		}
	}

	template<typename R,typename S>
	bool stof(const S *str,R &result)
	{
		if(!str)
			return(false);

		R pos=10;
		bool zf=true;

		result=0;

		if(*str=='-')
		{
			zf=false;
			str++;
		}

		while(*str)
		{
			if(*str>='0'&&*str<='9')
			{
				result*=10;
				result+=(*str-'0');
			}
			else
				if(*str=='.')
					break;
				else
				{
					if(!zf)
						result=-result;

					return(true);
				}

				str++;
		}

		str++;	//跳过小数点

		while(*str)
		{
			if(*str>='0'&&*str<='9')
			{
				result+=R(*str-'0')/pos;

				pos*=10;

				str++;
			}
			else
			{
				if(!zf)
					result=-result;

				return(true);
			}
		}
	}

	/**
	 * 转换一个字符串到bool型
	 * @param str 要转换的字符串
	 * @return 转换后的值
	 */
	template<typename T>
	bool stob(const T *str)
	{
		if(!str)return(false);

		if(*str=='T'||*str=='t'
		 ||*str=='1')return(true);

		return(false);
	}

	template<typename T,typename I>
	T *itos(T *str,int size,I value)
	{
		if(!str||size<=0)return(NULL);

		T *p=str;
		T buf[sizeof(I)*8],*bp;

		if(value<0)
		{
			*p++=L'-';
			size--;

			value=-value;
		}

		bp=buf;

		while(true)
		{
			*bp++=(value%10)+'0';

			if ((value = value / 10) == 0)
				break;
		}

		while(bp--!=buf&&size--)
			*p++=*bp;

		*p=0;

		return(str);
	}

	template<typename T,typename U>
	T *utos(T *str,int size,U value)
	{
		if(!str||size<=0)return(NULL);

		T *p=str;
		T buf[sizeof(U)*8],*bp;

		bp=buf;

		while(true)
		{
			*bp++=(value%10)+'0';

			if ((value = value / 10) == 0)
				break;
		}

		while(bp--!=buf&&size--)
			*p++=*bp;

		*p=0;

		return(str);
	}

	/**
	 * 转换一个浮点数到字符串
	 * @param str 字符串保存指针
	 * @param size 字符串保存空间长度
	 * @param fsize 小数部分保留长度
	 * @param value 要转换的值
	 */
	template<typename T,typename F>
	T *ftos(T *str,int size,int fsize,F value)
	{
		const int64 integer=(int)value;		//整数部分

		itos(str,size,value);

		int len=strlen(str);

		if(len>=size)
			return(str);

		T *p=str+len;

		value-=integer;						//保留小数部分

		if(value==0)
			return(str);

		*p++=L'.';							//加小数点
		len++;

		//由于第一代码直接取走了整数部分时包含正负值，所以最终value剩下的部分也会是正数

		while(value>0&&len<size&&fsize--)
		{
			value*=10;						//让最上一位变成个位数
			*p++='0'+value;

			value-=int(value);				//减去整数部分
			len++;
		}

		*p=0;
		return(str);
	}

	/**
	 * 转换一个整数到计算机表示法
	 * @param str 字符串保存指针
	 * @param size 字符串保存空间长度
	 * @param value 要转换的值
	 * @return 是否转换成功
	 */
	template<typename T,typename V>
	bool IntToSize(T *str,int size,V value)
	{
		const T name[]={'K','M','G','T','P','E','Z','Y'};

		double new_value=value;
		int pos=0;

		while(new_value>=1024&&size--)
		{
			pos++;
			new_value/=1024;

			if(name[pos]==0)
				return(false);	//太大了
		}

		const float f=new_value;

		ftos(str,size,2,f);

		T *p=str+strlen(str);

		if(pos)
			*p++=name[pos-1];

		*p++='B';
		*p=0;

		return(true);
	}
}//namespace hgl
#endif//HGL_STR_TEMPLATE_INCLUDE
